﻿#region << 版 本 注 释 >>
/*----------------------------------------------------------------
// Copyright (C) 2021 kingerrobot
// 版权所有。 
//
// 文件名：BTask
// 文件功能描述：
//
// 创建者：名字 (zzl)
// 时间：2021/12/6 15:05:46
//
// 修改人：
// 时间：
// 修改说明：
// 版本：V1.0.0
//----------------------------------------------------------------*/
#endregion

using KingerRobot.MexicoSailunMDC.Dao;
using System.Threading.Tasks;

namespace KingerRobot.MexicoSailunWMS.SpiService;
internal class BTask : ITask
{
    private readonly static ITaskCmd _TaskCmd = new BTaskCmd();
    private readonly static IProdProduct _ProdProduct = new BProdProduct();
    private readonly static IWcsEquipLoc _WcsEquipLoc = new BWcsEquipLoc();
    private readonly static IWcsNetAbnormal _WcsNetAbnormal = new BWcsNetAbnormal();
    private readonly static IWcsLocSku _WcsLocSku = new BWcsLocSku();

    public POWcsTask GetTaskByProductCode(string productCode)
    {
        var skuId = _ProdProduct.GetSkuIdByCode(productCode);

        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.SkuId == skuId)
            .FirstOrDefault();
        return result;
    }
    public List<POWcsTask> GetTaskList()
    {

        var db = Db.Default;
        var result = db.WcsTasks.ToList();
        return result;
    }
    public long GetTaskIdByProductCode(string productCode) => GetTaskByProductCode(productCode)?.Id ?? 0;
    public bool HasTaskByProductCode(string productCode) => GetTaskByProductCode(productCode) != null;

    public List<POWcsTask> GetTasksByMasterId(long masterId)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.MasterId == masterId)
            .ToList();
        return result;
    }
    public POWcsTask GetTasksBySummaryId(long summaryId)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.SummaryId == summaryId)
            .FirstOrDefault();
        return result;
    }
    public long CreateOutAbnormalTask(long startLoc, long skuId, string remark)
    {
        var abnormal = _WcsNetAbnormal.GetWcsNetAbnormalByStartLoc(startLoc);
        if (abnormal is null)
        {
            return 0;
        }
        var targetLoc = abnormal.TargetLoc.GetValueOrDefault();
        long startEquip = _WcsEquipLoc.GetEquipIdByLocId(startLoc); // 获取开始设备
        long targetEquip = _WcsEquipLoc.GetEquipIdByLocId(targetLoc); // 获取目标设备
        POWcsTask pOWcsTask = new()
        {
            Id = XID.Nextval,
            TaskNo = K8.LSF.Client.CodeValue(new DateTime(),"TaskNo").ToInt(0),
            SkuId = skuId,
            StartEquip = startEquip,
            StartLoc = startLoc,
            CurrentEquip = startEquip,
            CurrentLoc = startLoc,
            TargetEquip = targetEquip,
            TargetLoc = targetLoc,
            TaskStatus = (int?)EnumTaskStatus.Executable,
            TaskType = (int)EnumTaskType.Transportation,
            IsAbnormal = true,
            RemarkMemo = remark,
            TooltipMemo = remark,
        };

        var db = Db.Default;
        db.WcsTasks.Insert(pOWcsTask);
        return pOWcsTask.Id.GetValueOrDefault();
    }
    public List<POWcsTask> GetTaskByType(int type)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .OrderBy(t => t.CreateTime)
            .ToList();
        if (type != 0)
        {
            result = result.Where(t => t.TaskType == type).ToList();
        }
        return result;
    }
    //OLDTODO 【已解决】分成入库出库两个函数调用， 添加一个状态判断 < 2 [可执行]
    public List<POWcsTask> GetIOExecutableWcsTasksByType(EnumTaskType enumTaskType) => enumTaskType switch
    {   //下面有改动 lsq
        EnumTaskType.Warehousing => GetTaskByType((int)EnumTaskType.Warehousing).Where(t => t.TaskStatus < (int)EnumTaskStatus.Executed).ToList(),
        EnumTaskType.Exwarehouse => GetTaskByType((int)EnumTaskType.Exwarehouse).Where(t => t.TaskStatus < (int)EnumTaskStatus.Executed).ToList(),
        _ => new List<POWcsTask>(),
    };
    public List<POWcsTask> GetAllTasksByTargetLoc(long targetLoc)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.TargetLoc == targetLoc)
            .ToList();
        return result;
    }
    public int GetTaskCountByTargetLoc(long targetLoc) => GetAllTasksByTargetLoc(targetLoc).Count;
    public bool GetHasTaskByTargetLoc(long targetLoc) => GetAllTasksByTargetLoc(targetLoc) != null;
    public POWcsTask GetTaskBySkuId(long skuId)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.SkuId == skuId)
            .FirstOrDefault();
        return result;
    }
    public List<POWcsTask> GetTaskBySkuIds(List<long?> skuIds)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => skuIds.Contains(t.SkuId))
            .ToList();
        return result;
    }
    public List<POWcsTask> GetTasksByGroupNo(long groupNo)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.TaskGroup == groupNo)
            .ToList();
        return result;
    }

    public POWcsTask GetTaskByTaskId(long taskId)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.Id == taskId).AsNoTracking()
            .FirstOrDefault();
        return result;
    }
    public POWcsTask GetExecutedTaskByTaskId(long taskId)
    {
        var result = GetTaskByTaskId(taskId);
        return result.TaskStatus < (int)EnumTaskStatus.Finish ? result : null;
    }
    public long GetTargetIdByTaskId(long taskId) => GetTaskByTaskId(taskId)?.TargetLoc ?? 0;

    public POWcsTask GetTaskByTaskNo(int taskNo)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.TaskNo == taskNo)
            .FirstOrDefault();
        return result;
    }
    public POWcsTask GetExecutableTaskByTaskNo(int taskNo)
    {
        var result = GetTaskByTaskNo(taskNo);
        if (result == null)
        {
            return null;
        }
        else
        {
            var cmdResult = _TaskCmd.GetTaskCmdByTaskId(result.Id.GetValueOrDefault());
            if (cmdResult != null && cmdResult.CmdStatus < (int)EnumTaskCmdStatus.Executed)
            {
                return result;
            }

        }
        return null;
    }
    public POWcsTask GetDistributionLocByTaskNo(int taskNo)
    {
        var result = GetTaskByTaskNo(taskNo);
        return result?.TaskStatus == (int)EnumTaskStatus.Executed ? result : null;
    }
    public POWcsTask GetExecutedByTaskNo(int taskNo)
    {
        var result = GetTaskByTaskNo(taskNo);
        if (result == null)
        {
            return null;
        }
        else
        {
            var cmdResult = _TaskCmd.GetTaskCmdByTaskId(result.Id.GetValueOrDefault());
            if (cmdResult != null && cmdResult.CmdStatus >= (int)EnumTaskCmdStatus.Executed)
            {
                return result;
            }

        }
        return null;

    }
    public POWcsTask GetExecutedTaskByTaskNo(int taskNo)
    {
        var result = GetTaskByTaskNo(taskNo);
        return result.TaskStatus == (int)EnumTaskStatus.Executed ? result : null;
    }
    public POWcsTask GetLastTaskByLocId(long locId, int type)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.StartLoc == locId && t.TaskType == type).OrderByDescending(t => t.CreateTime)
            .FirstOrDefault();
        return result;
    }

    public List<TaskGroupCount> GetMaterialTaskGroup()
    {
        var db = Db.Default;
        var result = db.WcsTasks.Join(db.ProdSkus, f => f.SkuId, s => s.Id, (f, s) => new { TargetLoc = f.TargetLoc, MaterialId = s.MaterialId })
            .GroupBy(s => s.TargetLoc)
            .Select(t => new TaskGroupCount
            {
                LocId = t.Key,
                Count = t.Count(),
            }).ToList();
        return result;
    }
    public List<TaskGroupCount> GetTargetLocTaskGroup()
    {
        var db = Db.Default;
        var result = db.WcsTasks.GroupBy(t => t.TargetLoc)
            .Select(t => new TaskGroupCount
            {
                LocId = t.Key.Value,
                Count = t.Count()
            }).ToList();
        return result;
    }
    public List<TaskGroupCount> GetStartLocTaskGroup()
    {
        var db = Db.Default;
        var result = db.WcsTasks.GroupBy(t => t.StartLoc)
            .Select(t => new TaskGroupCount
            {
                LocId = t.Key.Value,
                Count = t.Count()
            }).ToList();
        return result;
    }

    public POWcsTask GetExecutableTaskByLocId(long locId)
    {
        var db = Db.Default;
        var result = db.WcsTasks.Join(db.WcsTaskCmds, a => a.Id, b => b.TaskId, (a, b) => new
        {
            Task = a,
            Cmd = b,
        })
            .Where(t => t.Cmd.StartLoc == locId && t.Cmd.CmdStatus < (int)EnumTaskStatus.Executed).Select(t => t.Task)
            .FirstOrDefault();
        return result;
    }
    public long GetExecutableTaskIdkByLocId(long locId) => GetExecutableTaskByLocId(locId)?.Id ?? 0;


    public void EditTaskType(long taskId, int type)
    {
        var db = Db.Default;
        var task = db.WcsTasks.Where(x => x.Id == taskId).FirstOrDefault();
        if (task is null)
        {
            return;
        }
        task.TaskType = type;
        db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            TaskType = type
        });
    }

    public void UpdateTaskCallDelete(long taskId, int calldelete)
    {
        var db = Db.Default;
        var task = db.WcsTasks.Where(x => x.Id == taskId).FirstOrDefault();
        if (task is null)
        {
            return;
        }
        task.CallDelete = calldelete;
        db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            CallDelete = calldelete
        });
    }




    public int UpdateTaskStatus(long locId, long taskId, int status)
    {
        var task = GetTaskByTaskId(taskId);
        if (task is null)
        {
            return 0;
        }
        long? finishLoc = null;
        int? finishMode = (int)EnumTaskStatus.Create;
        DateTime? finishTime = null;
        //加上了入库前验证  lsq
        if (status == (int)EnumTaskStatus.Finish)
        {
            // 完成时修改
            finishLoc = locId;
            finishMode = (int)EnumFinishMode.NormalEnd;
            finishTime = DateTime.Now;
        }
        var db = Db.Default;
        return db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            TaskStatus = status,
            UpdateTime = DateTime.Now,
            FinishLoc = finishLoc,
            FinishMode = finishMode,
            FinishTime = finishTime
        });
    }

    public int UpdateTaskStatusByTaskIds(List<long> taskIds, int status)
    {
        long? finishLoc = null;
        int? finishMode = (int)EnumTaskStatus.Create;
        DateTime? finishTime = null;

        var db = Db.Default;
        return db.WcsTasks
            .Where(t => taskIds.Contains(t.Id.GetValueOrDefault()))
            .Update( new POWcsTask
            {
                TaskStatus = status,
                UpdateTime = DateTime.Now,
                FinishLoc = finishLoc,
                FinishMode = finishMode,
                FinishTime = finishTime
            });
    }

    public int UpdateTaskSpray(long taskId, int isSpray)
    {

        var db = Db.Default;
        return db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            IsSpray = isSpray,
        });
    }
    public int UpdateTaskReamrkByTaskId(long taskId, string remark)
    {
        var db = Db.Default;
        var result = db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            RemarkMemo = remark
        });
        return result;
    }
    public int UpdateTaskAndCmdStatusForManualEnd(long locId, long taskId, int status) => status switch
    {
        (int)EnumTaskStatus.Executable => UpdateTaskStatusForManualEnd(locId, taskId, (int)EnumTaskStatus.Executable) & _TaskCmd.UpdateTaskCmdStatusForManualEnd(locId, taskId, (int)EnumTaskCmdStatus.Executable),
        (int)EnumTaskStatus.Executed => UpdateTaskStatusForManualEnd(locId, taskId, (int)EnumTaskStatus.Executed) & _TaskCmd.UpdateTaskCmdStatusForManualEnd(locId, taskId, (int)EnumTaskCmdStatus.Executed),
        (int)EnumTaskStatus.Finish => UpdateTaskStatusForManualEnd(locId, taskId, (int)EnumTaskStatus.Finish) & _TaskCmd.UpdateTaskCmdStatusForManualEnd(locId, taskId, (int)EnumTaskCmdStatus.Finish),
        _ => 0,
    };

    public int UpdateTaskStatusForManualEnd(long locId, long taskId, int status)
    {
        var task = GetTaskByTaskId(taskId);
        if (task is null)
        {
            return 0;
        }
        long? finishLoc = null;
        int? finishMode = (int)EnumTaskStatus.Create;
        DateTime? finishTime = null;
        //加上了入库前验证  lsq
        if (status == (int)EnumTaskStatus.Finish)
        {
            // 完成时修改
            finishLoc = locId;
            finishMode = (int)EnumFinishMode.ManualEnd;
            finishTime = DateTime.Now;
        }
        var db = Db.Default;
        return db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            TaskStatus = status,
            UpdateTime = DateTime.Now,
            FinishLoc = finishLoc,
            FinishMode = finishMode,
            FinishTime = finishTime
        });
    }
    // Func<int,int>
    public int UpdateTaskAndCmdStatus(long locId, long taskId, int status) => status switch
    {
        (int)EnumTaskStatus.Executable => UpdateTaskStatus(locId, taskId, (int)EnumTaskStatus.Executable) & _TaskCmd.UpdateTaskCmdStatus(locId, taskId, (int)EnumTaskCmdStatus.Executable),
        (int)EnumTaskStatus.Executed => UpdateTaskStatus(locId, taskId, (int)EnumTaskStatus.Executed) & _TaskCmd.UpdateTaskCmdStatus(locId, taskId, (int)EnumTaskCmdStatus.Executed),
        (int)EnumTaskStatus.Finish => UpdateTaskStatus(locId, taskId, (int)EnumTaskStatus.Finish) & _TaskCmd.UpdateTaskCmdStatus(locId, taskId, (int)EnumTaskCmdStatus.Finish),
        _ => 0,
    };

    // Func<int,int>
    public int UpdateTaskAndCmdStatusByTaskIds(List<long> taskIds, int status) => status switch
    {
        (int)EnumTaskStatus.Executable => UpdateTaskStatusByTaskIds(taskIds, (int)EnumTaskStatus.Executable) + _TaskCmd.UpdateTaskCmdStatusByTaskIds(taskIds, (int)EnumTaskCmdStatus.Executable),
        _ => 0,
    };

    public int BakTask(long taskId)
    {
        var task = GetTaskByTaskId(taskId);
        if (task is null)
        {
            return 0;
        }
        var db = Db.Default;

        var result = 0;
        try { result = db.BakWcsTasks.CopyFrom(task); }
        catch (Exception ex)
        {
            //WriteLog(ex.ToString()); 
        };
        return result;
    }
    public int BakAndDeleteTask(long taskId)
    {
        var bak = BakTask(taskId);
        if (bak == 0)
        {
            return 0;
        }
        var del = DeleteTask(taskId);
        return del & bak;
    }
    public int BakAndDeleteTaskAndCmd(long taskId)
    {
        var task = BakAndDeleteTask(taskId);
        if (task == 0)
        {
            return 0;
        }

        var cmd = _TaskCmd.BakAndDeleteCmd(taskId);

        return task & cmd;
    }
    public int DeleteBindLocInfoByTask(POWcsTask task)
    {
        if (task == null)
        { return 0; }
        int result = 0;
        result += _WcsLocSku.DeleteWcsLocSkuByLoc(task.StartLoc);
        result += _WcsLocSku.DeleteWcsLocSkuByLoc(task.CurrentLoc);
        result += _WcsLocSku.DeleteWcsLocSkuByLoc(task.TargetLoc);
        return result;
    }
    public int DeleteTask(long taskId)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.Id == taskId).Delete();

        return result;
    }

    private POWcsTask GetTaskByEquipId(long equipId)
    {
        var db = Db.Default;
        var result = db.WcsTasks
            .Where(t => t.StartEquip == equipId)
            .FirstOrDefault();
        return result;
    }
    public int UpdateTaskTargetLoc(long taskId, long targetLoc)
    {
        var task = GetTaskByTaskId(taskId);
        if (task is null)
        {
            return 0;
        }

        var db = Db.Default;
        return db.WcsTasks.Where(t => t.Id == taskId).Update( new POWcsTask
        {
            TargetLoc = targetLoc
        });
    }
    public bool IsTaskByEquipId(long equipId) => GetTaskByEquipId(equipId) is not null;

    public List<TaskMaterial> GetTaskMaterial(List<long?> taskIds)
    {
        var db = Db.Default;
        var result = db.WcsTasks.Join(db.ProdSkus, f => f.SkuId, s => s.Id, (f, s) => new TaskMaterial
        {
            TaskId = f.Id.GetValueOrDefault(),
            MaterialId = s.MaterialId.GetValueOrDefault(),
        }).Where(t => taskIds.Contains(t.TaskId)).ToList();
        return result;
    }

    public List<TaskProductBean> GetTaskProduct()
    {
        var db = Db.Default;
        var skuProduct = GetSkuProductBeans();
        var result = db.WcsTasks.ToList().GroupJoin(skuProduct, f => f.SkuId, s => s.POProdSkuProduct.SkuId, (f, s) => new
        {

            Task = f,
            SkuProduct = s,

        }).SelectMany(f => f.SkuProduct.DefaultIfEmpty(), (f, s) => new TaskProductBean
        {
            POWcsTask = f.Task,
            POProdProduct = s?.POProdProduct,
        }).ToList();


        return result;
    }

    public List<SkuProductBean> GetSkuProductBeans()
    {
        var db = Db.Default;
        var result = db.ProdSkuProducts.Join(db.ProdProducts, f => f.ProductId, s => s.Id, (f, s) => new SkuProductBean
        {
            POProdSkuProduct = f,
            POProdProduct = s
        }).ToList();
        return result;
    }




    List<Spi.TaskStatus> ITask.GetTaskStatus()
    {
        List<Spi.TaskStatus> list = new();
        list.Add(new Spi.TaskStatus() { StatusDesc = "创建", StatusKey = 0 });
        list.Add(new Spi.TaskStatus() { StatusDesc = "可执行", StatusKey = 1 });
        list.Add(new Spi.TaskStatus() { StatusDesc = "已执行", StatusKey = 2 });
        list.Add(new Spi.TaskStatus() { StatusDesc = "任务完成", StatusKey = 9 });

        return list;
    }

    public List<POVTasks> GetVTasks()
    {
        var db = Db.Default;
        var result = db.VTasks.ToList();
        return result;
    }

    public List<POVTasks> GetVTasksOrderBy(string OrderByType, string OrderByName)
    {
        var db = Db.Default;
        var result = new List<POVTasks>();
        var data = db.VTasks.Where(t=>true);
        if (!String.IsNullOrWhiteSpace(OrderByName))
        {
            if (OrderByType == "ASC")
            {
                result = data.OrderBy(OrderByName).ToList();
            }
            else
            {
                result = data.OrderByDescending(OrderByName).ToList();
            }
        }
        else
        {
            result = data.ToList();
        }

        return result;
    }
    public int DelTaskIdByProductCode(string productCode)
    {
        var db = Db.Default;
        var result = 0;
        var product = db.ProdProducts.Where(f => f.ProductCode == productCode).FirstOrDefault();

        if (product != null)
        {
            var SkuProduct = db.ProdSkuProducts.Where(f => f.ProductId == product.Id).FirstOrDefault();
            if (SkuProduct != null)
            {
                var WcsTask = db.WcsTasks.Where(f => f.SkuId == SkuProduct.SkuId).FirstOrDefault();
                if (WcsTask != null)
                {

                    return WcsTask.TaskNo.GetValueOrDefault();
                }
            }
        }

        return result;
    }
}

